﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GiMessCommons;
using System.Windows.Forms;

namespace GiMessServer.Net
{
    public class NetMsgHandler
    {
        //private DataFieldsReader dataReader;
        //private DataFieldsWriter dataWriter;
        
        public void HandleMsg(NetClient sender, NetMsg msg)
        {
            Loger.LogLine("Message", Loger.ServerLogLevel.Verbose);
            Loger.LogLine(((NetServices)msg.Service).ToString(), Loger.ServerLogLevel.Verbose);
            Loger.LogLine(msg.Data, Loger.ServerLogLevel.Verbose);
            switch ((NetServices)msg.Service)
            {
                case NetServices.Auth:
                    UserAuth(sender, msg);
                    break;
                case NetServices.SignOut:
                    UserSignOut(sender);
                    break;
                case NetServices.ContactDelete:
                    UserContactDelete(sender, msg);
                    break;
                case NetServices.ContactMove:
                    UserContactMove(sender, msg);
                    break;
                case NetServices.GroupCreate:
                    UserGroupCreate(sender, msg);
                    break;
                case NetServices.GroupRename:
                    UserGroupRename(sender, msg);
                    break;
                case NetServices.ListRequest:
                    SendList(sender, msg);
                    break;
                case NetServices.SendMessage:
                    GiMessServer.Instance.UserIM(msg.Data);
                    break;
                case NetServices.UpdateAvatar:
                    UserUpdateField(sender, msg, NetServices.UpdateAvatar, Field.UpdateAvatar);
                    break;
                case NetServices.UpdateStatus:
                    UserUpdateField(sender, msg, NetServices.UpdateStatus, Field.UpdateStatus);
                    break;
                case NetServices.CreateAccount:
                    CreateAccount(sender, msg);
                    break;
                case NetServices.ContactAdd:
                    UserAddFriend(sender, msg);
                    break;
                case NetServices.AddRequestResponse:
                    UserAddFriendResponse(sender, msg);
                    break;
            }
        }

        private void UserAddFriendResponse(NetClient sender, NetMsg msg)
        {
            DataFieldsReader dataReader = new DataFieldsReader(msg.Data);

            string username = dataReader.GetFieldData(Field.AddUserName);
            string response = dataReader.GetFieldData(Field.AddResponse);
            bool boolResp = bool.Parse(response);

            Database.HandleFriendRequest(sender.Credidentials.UserName, username, boolResp);

            //trimitei lu username un nou utilizator in lista
            if (boolResp)
            {
                string groupName = Database.GetRequestGroupName(sender.Credidentials.UserName, username);
                SendListUser(username, sender.Credidentials.UserName, groupName);
            }           
        }

        private void SendListUser(string toUserName, string friendUserName, string groupName)
        {
            try
            {
                DataFieldsWriter dataWriter = new DataFieldsWriter();

                dataWriter.WriteField(Field.ListCount, "1");
                dataWriter.WriteField(Field.ListUserGroup, groupName);
                dataWriter.WriteField(Field.ListUserName, friendUserName);
                dataWriter.WriteField(Field.ListUserFirstName, Database.GetFirstName(friendUserName));
                dataWriter.WriteField(Field.ListUserLastName, Database.GetLastName(friendUserName));
                dataWriter.WriteField(Field.ListUserOnline, Database.GetOnlineStatus(friendUserName).ToString());
                dataWriter.WriteField(Field.ListUserStatus, Database.GetStatus(friendUserName));
                dataWriter.WriteField(Field.ListUserAvatar, Database.GetAvatar(friendUserName));

                NetMsg msg = new NetMsg(NetServices.ListSend, dataWriter.GetString());

                GiMessServer.Instance.SendNetMessage(toUserName, msg);
            }
            catch (UserNotFoundException unfex)
            {

                Loger.LogLine(unfex.Message, Loger.ServerLogLevel.Verbose);
            }
        }

        private void UserAddFriend(NetClient sender, NetMsg msg)
        {
            DataFieldsReader dataReader = new DataFieldsReader(msg.Data);

            string addUserName  = dataReader.GetFieldData(Field.AddUserName);
            string addUserGroup = dataReader.GetFieldData(Field.AddUserGroup);

            Database.AddFriendRequest(sender.Credidentials.UserName, addUserName, addUserGroup);

            NetMsg reqMsg = new NetMsg(NetServices.AddRequest, sender.Credidentials.UserName);

            GiMessServer.Instance.SendNetMessage(addUserName, reqMsg);
        }

        private void UserGroupRename(NetClient sender, NetMsg msg)
        {
            DataFieldsReader dataReader = new DataFieldsReader(msg.Data);

            string oldName = dataReader.GetFieldData(Field.ListUserGroup);
            string newName = dataReader.GetFieldData(Field.ListUserGroupRename);

            Database.GroupRename(sender.Credidentials.UserName, oldName, newName);
        }

        private void UserContactMove(NetClient sender, NetMsg msg)
        {
            DataFieldsReader dataReader = new DataFieldsReader(msg.Data);

            string friend = dataReader.GetFieldData(Field.ListUserName);
            string group  = dataReader.GetFieldData(Field.ListUserGroup);

            Database.MoveFriend(sender.Credidentials.UserName, friend, group);
        }

        private void UserGroupCreate(NetClient sender, NetMsg msg)
        {
            Database.AddGroup(sender.Credidentials.UserName, msg.Data);
        }

        private void UserContactDelete(NetClient sender, NetMsg msg)
        {
            Database.DeleteFriend(sender.Credidentials.UserName, msg.Data);
        }

        public  void UserSignOut(NetClient sender)
        {
            Database.SetOnlineStatus(sender.Credidentials.UserName, false);
            NotifyFriends(sender.Credidentials.UserName, "false");
        }

        private void CreateAccount(NetClient sender, NetMsg msg)
        {
            string userName, password, firstName, lastName, email;

            DataFieldsReader dataReader;
            dataReader = new DataFieldsReader(msg.Data);
            userName   = dataReader.GetFieldData(Field.NewAccUserName);
            password   = dataReader.GetFieldData(Field.NewAccPassword);
            firstName  = dataReader.GetFieldData(Field.NewAccFirstName);
            lastName   = dataReader.GetFieldData(Field.NewAccLastName);
            email      = dataReader.GetFieldData(Field.NewAccEmail);

            try
            {
                Database.AddUser(userName, password, firstName, lastName, email);
                sender.SendNetMsg(NetServices.CreateAccSucces, "");
            }
            catch (System.Data.DataException e)
            {
                sender.SendNetMsg(NetServices.CreateAccFaied, "Username already exists");
            }
            catch
            {
                sender.SendNetMsg(NetServices.CreateAccFaied, "Unknown error");
            }

        }

        private void UserAuth(NetClient sender, NetMsg msg)
        {
            try
            {
                string userName;
                string userPass;

                DataFieldsWriter dataWriter;
                DataFieldsReader dataReader;
                dataReader = new DataFieldsReader(msg.Data);
                userName = dataReader.GetFieldData(Field.AuthUserName);
                userPass = dataReader.GetFieldData(Field.AuthUserPassword);

                //GiMessServer.Instance.UserLogin(sender, userName, userPass);

                if (CheckCredidentials(userName, userPass))
                {
                    dataWriter = new DataFieldsWriter();
                    dataWriter.WriteField(Field.AuthUserFristName, Database.GetFirstName(userName));
                    dataWriter.WriteField(Field.AuthUserLastName, Database.GetLastName(userName));
                    dataWriter.WriteField(Field.AuthUserAvatar, Database.GetAvatar(userName));

                    sender.SendNetMsg(NetServices.LoginAccepted, dataWriter.GetString());

                    sender.Credidentials = new AuthInfo(userName);

                    Database.SetOnlineStatus(userName, true);

                    NotifyFriends(userName, "true");
                    //set sender AuthInfo
                    //GiMessServer.Instance.AcceptLogin(sender);
                }
                else
                {
                    sender.SendNetMsg(NetServices.LoginFailed, "");
                }
            }
            catch (UserNotFoundException unfex)
            {
                Loger.LogLine(unfex.Message, Loger.ServerLogLevel.Verbose);
            }
        }

        private void NotifyFriends(string userName, string online)
        {
            UserFriend[] friends = Database.GetUserList(userName);
            DataFieldsWriter dataWriter;

            dataWriter = new DataFieldsWriter();
            dataWriter.WriteField(Field.UpdateUserName, userName);
            dataWriter.WriteField(Field.UpdateOnline, online);

            NetMsg msg = new NetMsg(NetServices.UpdateOnline, dataWriter.GetString());
            
            for (int i = 0; i < friends.Length; i++)
            {
                if (friends[i].Online)
                    GiMessServer.Instance.SendNetMessage(friends[i].Username, msg);
            }
        }

        private void SendList(NetClient sender, NetMsg msg)
        {
            UserFriend[] friends = Database.GetUserList(sender.Credidentials.UserName);

            DataFieldsWriter dataWriter;
            dataWriter = new DataFieldsWriter();
            dataWriter.WriteField(Field.ListCount, friends.Length.ToString());

            for(int i = 0; i<friends.Length; i++)
            {
                dataWriter.WriteField(Field.ListUserIndex,     i.ToString());
                dataWriter.WriteField(Field.ListUserGroup,     friends[i].Group);
                dataWriter.WriteField(Field.ListUserName,      friends[i].Username);
                dataWriter.WriteField(Field.ListUserFirstName, friends[i].FirstName);
                dataWriter.WriteField(Field.ListUserLastName,  friends[i].LastName);
                dataWriter.WriteField(Field.ListUserOnline,    friends[i].Online.ToString());
                dataWriter.WriteField(Field.ListUserStatus,    friends[i].Status);
                dataWriter.WriteField(Field.ListUserAvatar,    friends[i].Avatar);
            }

            sender.SendNetMsg(NetServices.ListSend, dataWriter.GetString());

            string[] groups = Database.GetUserGroups(sender.Credidentials.UserName);

            dataWriter = new DataFieldsWriter();
            dataWriter.WriteField(Field.ListCount, groups.Length.ToString());
            for (int i = 0; i < groups.Length; i++)
            {
                dataWriter.WriteField(Field.ListUserIndex, i.ToString());
                dataWriter.WriteField(Field.ListUserGroup, groups[i]);
            }
            sender.SendNetMsg(NetServices.ListGroupsSend, dataWriter.GetString());
        }

        private bool CheckCredidentials(string userName, string userPassword)
        {
            string dbPassword="";
            try
            {
                dbPassword = Database.GetUserPassword(userName);
            }
            catch (UserNotFoundException unfex)
            {
                //MessageBox.Show(unfex.Message);
            }
            finally
            {
                
            }
            return dbPassword.Equals(userPassword, StringComparison.Ordinal);
            
        }

        private void UserUpdateField(NetClient sender, NetMsg msg, NetServices service, Field field)
        {
            DataFieldsWriter dataWriter = new DataFieldsWriter();
            DataFieldsReader dataReader = new DataFieldsReader(msg.Data);

            string username    = sender.Credidentials.UserName;
            string updateValue = dataReader.GetFieldData(field);

            dataWriter.WriteField(Field.UpdateUserName, username);
            dataWriter.WriteField(field               , updateValue);

            NetMsg newMsg = new NetMsg(service, dataWriter.GetString());

            UserFriend[] friends = Database.GetUserList(username);

            for (int i = 0; i < friends.Length; i++)
            {
                if (friends[i].Online)
                    GiMessServer.Instance.SendNetMessage(friends[i].Username, newMsg);
            }
            UpdateDatabase(username, updateValue, field);
        }

        private void UpdateDatabase(string username, string value, Field field)
        {
            switch (field)
            {
                case Field.UpdateAvatar:
                    Database.SetAvatar(username, value);
                    break;
                case Field.UpdateStatus:
                    Database.SetStatus(username, value);
                    break;
                case Field.UpdateOnline:
                    Database.SetOnlineStatus(username, bool.Parse(value));
                    break;
            }
        }
    }
}
